use std::collections::HashSet;

use ndarray::{array, Array2};
use rstest::rstest;

use crate::tests::fixtures::{
    neighbor_association_tile_list,
    rand_bool,
    rand_usize,
    random_last_leaves,
    random_missing_tile_policy,
    random_predecessor,
    random_tile_selection_policy,
    RANDOM_USIZE,
    RANDOM_VACANCY_POLICY,
};
use crate::tiling::slot_grid::tests::{
    create_grid_slot_or_none,
    create_grid_slot_with_some_tile_id,
    pad_coordinates_randomly,
    pad_grid_randomly,
};
use crate::tiling::tiles::{ArrayInitializable, TileConnectionArray};
// There are identical arrays used in the following cases. Hard-coding and
// repetition is fine in test data, so
// noinspection DuplicatedCode
#[rstest]
// region NESW, no exposed edges present, one neighbor association, no wanted slot
#[case::nesw_no_exposed_edges_present_one_neighbor_association_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │       │
    // │       │
    // │       │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, None, None, None],
        [None, None, None, None],
        [None, None, None, None],
    ]),
    (
        vec![
            HashSet::from([
                Direction::North, Direction::East, Direction::South, Direction::West
            ]),
        ],
        false,
    ),
)]
// endregion
// region NESW, no exposed edges present, one neighbor association, wanted slot N found
#[case::nesw_no_exposed_edges_present_one_neighbor_association_wanted_slot_n_found(
    pad_coordinates_randomly((2, 2)),
    Some(pad_coordinates_randomly((1, 2))),
    // ╭───────╮
    // │   W   │
    // │       │
    // │       │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, None, None, None],
        [None, None, None, None],
        [None, None, None, None],
    ]),
    (vec![], true),
)]
// endregion
// region NESW, no exposed edges present, one neighbor association, wanted slot SE found
#[case::nesw_no_exposed_edges_present_one_neighbor_association_wanted_slot_se_found(
    pad_coordinates_randomly((2, 2)),
    Some(pad_coordinates_randomly((3, 3))),
    // ╭───────╮
    // │       │
    // │       │
    // │     W │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, None, None, None],
        [None, None, None, None],
        [None, None, None, None],
    ]),
    (vec![], true),
)]
// endregion
// region NESW, no exposed edges present, one neighbor association, wanted slot W found
#[case::nesw_no_exposed_edges_present_one_neighbor_association_wanted_slot_w_found(
    pad_coordinates_randomly((2, 2)),
    Some(pad_coordinates_randomly((2, 1))),
    // ╭───────╮
    // │       │
    // │ W     │
    // │       │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, None, None, None],
        [None, None, None, None],
        [None, None, None, None],
    ]),
    (vec![], true),
)]
// endregion
// region NESW, no exposed edges present, one neighbor association, occupied, no wanted slot
#[case::nesw_no_exposed_edges_present_one_neighbor_association_occupied_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │       │
    // │   1   │
    // │       │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, None, None, None],
        [None, None, create_grid_slot_with_some_tile_id(1), None],
        [None, None, None, None],
    ]),
    (
        vec![
            HashSet::from([
                Direction::North,
                Direction::East,
                Direction::South,
                Direction::West,
            ]),
        ],
        false,
    ),
)]
// endregion
// region NESW, no exposed edges present, one neighbor association, NE alt., no wanted slot
#[case::nesw_no_exposed_edges_present_one_neighbor_association_ne_alt_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │     0 │
    // │       │
    // │       │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, None, None, create_grid_slot_with_some_tile_id(0)],
        [None, None, None, None],
        [None, None, None, None],
    ]),
    (
        vec![
            HashSet::from([
                Direction::North,
                Direction::East,
                Direction::South,
                Direction::West,
            ]),
        ],
        false,
    ),
)]
// endregion
// region NESW, no exposed edges present, one neighbor association, NW alt., no wanted slot
#[case::nesw_no_exposed_edges_present_one_neighbor_association_nw_alt_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │ 0     │
    // │       │
    // │       │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, create_grid_slot_with_some_tile_id(0), None, None],
        [None, None, None, None],
        [None, None, None, None],
    ]),
    (
        vec![
            HashSet::from([
                Direction::North,
                Direction::East,
                Direction::South,
                Direction::West,
            ]),
        ],
        false,
    ),
)]
// endregion
// region NESW, no exposed edges present, one neighbor association, large, no wanted slot
#[case::nesw_no_exposed_edges_present_one_neighbor_association_large_no_wanted_slot(
    pad_coordinates_randomly((3, 3)),
    None,
    // ╭─────────╮
    // │         │
    // │         │
    // │         │
    // │         │
    // │         │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
    ]),
    (
        vec![
            HashSet::from([
                Direction::North,
                Direction::East,
                Direction::South,
                Direction::West,
            ]),
        ],
        false,
    ),
)]
// endregion
// region NESW, no exposed edges present, one neighbor association, large, wanted slot NW found
#[case::nesw_no_exposed_edges_present_one_neighbor_association_large_wanted_slot_nw_found(
    pad_coordinates_randomly((3, 3)),
    Some(pad_coordinates_randomly((2, 2))),
    // ╭───────────╮
    // │           │
    // │   W       │
    // │           │
    // │           │
    // │           │
    // ╰───────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
    ]),
    (vec![], true),
)]
// endregion
// region NESW, no exposed edges present, one neighbor association, large, wanted slot NW not found
#[case::nesw_no_exposed_edges_present_one_neighbor_association_large_wanted_slot_nw_not_found(
    pad_coordinates_randomly((3, 3)),
    Some(pad_coordinates_randomly((2, 1))),
    // ╭───────────╮
    // │           │
    // │ W         │
    // │           │
    // │           │
    // │           │
    // ╰───────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
        [None, None, None, None, None, None],
    ]),
    (
        vec![
            HashSet::from([
                Direction::North,
                Direction::East,
                Direction::South,
                Direction::West,
            ]),
        ],
        false,
    ),
)]
// endregion
// region NEW, S, no exposed edges present, one neighbor association, alt., no wanted slot
#[case::new_s_no_exposed_edges_present_one_neighbor_association_alt_no_wanted_slot(
    (2, 2),
    None,
    // ╭─────────╮
    // │         │
    // │         │
    // │ 0   0   │
    // │ 0       │
    // ╰─────────╯
    array![
        [None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            None,
        ],
        [
            None,
            None,
            None,
            None,
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            None,
        ],
    ],
    (
        vec![
            HashSet::from([
                Direction::North,
                Direction::East,
                Direction::South,
                Direction::West,
            ]),
        ],
        false,
    ),
)]
// endregion
// region NEW, S, no exposed edges present, two neighbor associations, no wanted slot
#[case::new_s_no_exposed_edges_present_two_neighbor_associations_no_wanted_slot(
    (2, 2),
    None,
    // ╭───────╮
    // │       │
    // │       │
    // │ 0   0 │
    // ╰───────╯
    array![
        [None, None, None, None],
        [None, None, None, None],
        [None, None, None, None],
        [None, create_grid_slot_with_some_tile_id(0), None, create_grid_slot_with_some_tile_id(0)],
    ],
    (
        vec![
            HashSet::from([Direction::North, Direction::East,Direction::West]),
            HashSet::from([Direction::South]),
        ],
        false,
    ),
)]
// endregion
// region NEW, S, no exposed edges present, two neighbor associations, alt., no wanted slot
#[case::new_s_no_exposed_edges_present_two_neighbor_associations_alt_no_wanted_slot(
    (2, 2),
    None,
    // ╭───────╮
    // │       │
    // │       │
    // │ 0   0 │
    // │ 0   0 │
    // ╰───────╯
    array![
        [None, None, None, None],
        [None, None, None, None],
        [None, None, None, None],
        [None, create_grid_slot_with_some_tile_id(0), None, create_grid_slot_with_some_tile_id(0)],
        [None, create_grid_slot_with_some_tile_id(0), None, create_grid_slot_with_some_tile_id(0)],
    ],
    (
        vec![
            HashSet::from([Direction::North, Direction::East, Direction::West]),
            HashSet::from([Direction::South]),
        ],
        false,
    ),
)]
// endregion
// region NEW, S, no exposed edges present, two neighbor associations, large alt., no wanted slot
#[case::new_s_no_exposed_edges_present_two_neighbor_associations_large_alt_no_wanted_slot(
    (2, 2),
    None,
    // ╭─────────╮
    // │         │
    // │         │
    // │ 0   0 0 │
    // │ 0       │
    // ╰─────────╯
    array![
        [None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            None,
        ],
        [
            None,
            None,
            None,
            None,
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            None,
        ],
    ],
    (
        vec![
            HashSet::from([Direction::North, Direction::East, Direction::West]),
            HashSet::from([Direction::South]),
        ],
        false,
    ),
)]
// endregion
// region NES, no exposed edges present, one neighbor association, no wanted slot
#[case::nes_no_exposed_edges_present_one_neighbor_association_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │       │
    // │ 0     │
    // │       │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, None, None, None],
        [None, create_grid_slot_with_some_tile_id(0), None, None],
        [None, None, None, None],
    ]),
    (vec![HashSet::from([Direction::North, Direction::East, Direction::South])], false),
)]
// endregion
// region NEW, no exposed edges present, one neighbor association, no wanted slot
#[case::new_no_exposed_edges_present_one_neighbor_association_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │       │
    // │       │
    // │   0   │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, None, None, None],
        [None, None, None, None],
        [None, None, create_grid_slot_with_some_tile_id(0), None],
    ]),
    (vec![HashSet::from([Direction::North, Direction::East, Direction::West])], false),
)]
// endregion
// region NSW, no exposed edges present, one neighbor association, no wanted slot
#[case::nsw_no_exposed_edges_present_one_neighbor_association_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │       │
    // │     0 │
    // │       │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, None, None, None],
        [None, None, None, create_grid_slot_with_some_tile_id(0)],
        [None, None, None, None],
    ]),
    (vec![HashSet::from([Direction::North, Direction::South, Direction::West])], false),
)]
// endregion
// region ESW, no exposed edges present, one neighbor association, no wanted slot
#[case::esw_no_exposed_edges_present_one_neighbor_association_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │   0   │
    // │       │
    // │       │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, None, create_grid_slot_with_some_tile_id(0), None],
        [None, None, None, None],
        [None, None, None, None],
    ]),
    (vec![HashSet::from([Direction::East, Direction::South, Direction::West])], false),
)]
// endregion
// region NEW, exposed edges present, no neighbor associations, no wanted slot
#[case::new_exposed_edges_present_no_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │       │
    // │       │
    // │   5   │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, None, None, None],
        [None, None, None, None],
        [None, None, create_grid_slot_with_some_tile_id(5), None],
    ]),
    (vec![], false),
)]
// endregion
// region NEW, exposed edges present, no neighbor associations, no wanted slot
#[case::new_exposed_edges_present_no_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │       │
    // │       │
    // │   3   │
    // │       │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, None, None, None],
        [None, None, None, None],
        [None, None, create_grid_slot_with_some_tile_id(3), None],
        [None, None, None, None],
    ]),
    (vec![], false),
)]
// endregion
// region NSW, exposed edges present, no neighbor associations, no wanted slot
#[case::nsw_exposed_edges_present_no_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │       │
    // │     1 │
    // │       │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, None, None, None],
        [None, None, None, create_grid_slot_with_some_tile_id(1)],
        [None, None, None, None],
    ]),
    (vec![], false),
)]
// endregion
// region ESW, exposed edges present, no neighbor associations, no wanted slot
#[case::esw_exposed_edges_present_no_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │   4   │
    // │       │
    // │       │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, None, create_grid_slot_with_some_tile_id(4), None],
        [None, None, None, None],
        [None, None, None, None],
    ]),
    (vec![], false),
)]
// endregion
// region ESW, exposed edges present, no neighbor associations, large, no wanted slot
#[case::esw_exposed_edges_present_no_neighbor_associations_large_no_wanted_slot(
    pad_coordinates_randomly((2, 3)),
    None,
    // ╭─────────╮
    // │     2   │
    // │         │
    // │         │
    // │         │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [None, None, None, create_grid_slot_with_some_tile_id(2), None],
        [None, None, None, None, None],
        [None, None, None, None, None],
        [None, None, None, None, None],
    ]),
    (vec![], false),
)]
// endregion
// region ESW, exposed edges present, no neighbor associations, large alt., no wanted slot
#[case::esw_exposed_edges_present_no_neighbor_associations_large_alt_no_wanted_slot(
    pad_coordinates_randomly((2, 3)),
    None,
    // ╭─────────╮
    // │   ₂ 0   │
    // │         │
    // │         │
    // │         │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(rand_usize(3, 5)),
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [
            None,
            None,
            None,
            None,
            None
        ],
        [
            None,
            None,
            None,
            None,
            None
        ],
        [
            None,
            None,
            None,
            None,
            None
        ],
    ]),
    (vec![], false),
)]
// endregion
// region ES, W, no exposed edges present, two neighbor associations, no wanted slot
#[case::es_w_no_exposed_edges_present_two_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((2, 3)),
    None,
    // ╭─────────╮
    // │ 0 0 0   │
    // │ 0       │
    // │ 0 0     │
    // │         │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [None, create_grid_slot_with_some_tile_id(0), None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
        ],
        [None, None, None, None, None],
    ]),
    (
        vec![
            HashSet::from([Direction::West]),
            HashSet::from([Direction::East, Direction::South]),
        ],
        false,
    ),
)]
// endregion
// region ES, W, no exposed edges present, two neighbor associations, alt., no wanted slot
#[case::es_w_no_exposed_edges_present_two_neighbor_associations_alt_no_wanted_slot(
    pad_coordinates_randomly((2, 4)),
    None,
    // ╭───────────╮
    // │ 0 0 0 0   │
    // │ 0         │
    // │ 0 0 0     │
    // │           │
    // ╰───────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            None,
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
        ],
        [
            None,
            None,
            None,
            None,
            None,
            None,
        ],
    ]),
    (
        vec![
            HashSet::from([Direction::West]),
            HashSet::from([Direction::East, Direction::South]),
        ],
        false,
    ),
)]
// endregion
// region ES, W, no exposed edges present, two neighbor associations, alt., wanted slot NE found
#[case::es_w_no_exposed_edges_present_two_neighbor_associations_alt_wanted_slot_ne_found(
    pad_coordinates_randomly((2, 4)),
    Some(pad_coordinates_randomly((1, 5))),
    // ╭───────────╮
    // │ 0 0 0 0 W │
    // │ 0         │
    // │ 0 0 0     │
    // │           │
    // ╰───────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            None,
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
        ],
        [
            None,
            None,
            None,
            None,
            None,
            None,
        ],
    ]),
    (vec![], true),
)]
// endregion
// region ES, W, no exposed edges present, two neighbor associations, alt., wanted slot NE not found
#[case::es_w_no_exposed_edges_present_two_neighbor_associations_alt_wanted_slot_ne_not_found(
    pad_coordinates_randomly((3, 4)),
    Some(pad_coordinates_randomly((2, 5))),
    // ╭─────────────╮
    // │         0   │
    // │ 0 0 0 0 W 0 │
    // │ 0       0   │
    // │ 0 0 0       │
    // │             │
    // ╰─────────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            None,
        ],
        [
            None,
            None,
            None,
            None,
            None,
            None,
            None,
        ],
    ]),
    (
        vec![
            HashSet::from([Direction::West]),
            HashSet::from([Direction::South]),
        ],
        false,
    ),
)]
// endregion
// region ES, W, exposed edges present, one neighbor association, no wanted slot
#[case::es_w_exposed_edges_present_one_neighbor_association_no_wanted_slot(
    pad_coordinates_randomly((2, 3)),
    None,
    // ╭─────────╮
    // │ 0 0 0   │
    // │ 0       │
    // │ 0 2     │
    // │         │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [None, create_grid_slot_with_some_tile_id(0), None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(2),
            None,
            None,
        ],
        [None, None, None, None, None],
    ]),
    (vec![HashSet::from([Direction::West])], false),
)]
// endregion
// region ES, W, exposed edges present, no neighbor associations, no wanted slot
#[case::es_w_exposed_edges_present_no_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((2, 3)),
    None,
    // ╭─────────╮
    // │ 0 0 0   │
    // │ 0       │
    // │ 0 ₂     │
    // │         │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [None, create_grid_slot_with_some_tile_id(0), None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(rand_usize(2, 4)),
            None,
            None,
        ],
        [None, None, None, None, None],
    ]),
    (vec![HashSet::from([Direction::West])], false),
)]
// endregion
// region ES, W, exposed edges present, one neighbor association, alt., no wanted slot
#[case::es_w_exposed_edges_present_one_neighbor_association_alt_no_wanted_slot(
    pad_coordinates_randomly((2, 3)),
    None,
    // ╭─────────╮
    // │ 0 0 0   │
    // │ 0       │
    // │ 3 0     │
    // │         │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [None, create_grid_slot_with_some_tile_id(0), None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(3),
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
        ],
        [None, None, None, None, None],
    ]),
    (vec![HashSet::from([Direction::West])], false),
)]
// endregion
// region N, E, S, no exposed edges present, three neighbor associations, no wanted slot
#[case::n_e_s_no_exposed_edges_present_three_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((3, 3)),
    None,
    // ╭─────────╮
    // │   0 0 0 │
    // │ 0 0   0 │
    // │ 0 0     │
    // │ 0 0   0 │
    // │   0 0 0 │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
    ]),
    (
        vec![
            HashSet::from([Direction::South]),
            HashSet::from([Direction::East]),
            HashSet::from([Direction::North]),
        ],
        false,
    ),
)]
// endregion
// region N, E, W, no exposed edges present, three neighbor associations, no wanted slot
#[case::n_e_w_no_exposed_edges_present_three_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((3, 3)),
    None,
    // ╭─────────╮
    // │   0 0 0 │
    // │ 0 0   0 │
    // │ 0       │
    // │ 0 0 0 0 │
    // │   0 0 0 │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [None, create_grid_slot_with_some_tile_id(0), None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
    ]),
    (
        vec![
            HashSet::from([Direction::West]),
            HashSet::from([Direction::East]),
            HashSet::from([Direction::North]),
        ],
        false,
    ),
)]
// endregion
// region E, S, W, no exposed edges present, three neighbor associations, no wanted slot
#[case::e_s_w_no_exposed_edges_present_three_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((2, 3)),
    None,
    // ╭─────────╮
    // │ 0 0 0   │
    // │ 0       │
    // │ 0 0   0 │
    // │   0 0 0 │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [None, create_grid_slot_with_some_tile_id(0), None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
    ]),
    (
        vec![
            HashSet::from([Direction::West]),
            HashSet::from([Direction::South]),
            HashSet::from([Direction::East]),
        ],
        false,
    ),
)]
// endregion
// region N, E, S, exposed edges present, two neighbor associations, no wanted slot
#[case::n_e_s_exposed_edges_present_two_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((3, 3)),
    None,
    // ╭─────────╮
    // │   0 0 0 │
    // │ 0 0   3 │
    // │ 0 0     │
    // │ 0 0   0 │
    // │   0 0 0 │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(3),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
    ]),
    (vec![HashSet::from([Direction::South]), HashSet::from([Direction::North])], false),
)]
// endregion
// region NE, S, no exposed edges present, three neighbor associations, no wanted slot
#[case::ne_s_no_exposed_edges_present_three_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((4, 4)),
    None,
    // ╭─────────────╮
    // │ 0 0 0 0 0   │
    // │ 0       0   │
    // │ 0   0   0   │
    // │     0       │
    // │   0 0   0   │
    // │     0 0 0   │
    // │ 0           │
    // │ 0           │
    // ╰─────────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            None,
        ],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            None,
            None,
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            None,
            None,
            None,
        ],
    ]),
    (
        vec![
            HashSet::from([Direction::South]),
            HashSet::from([Direction::North, Direction::East]),
        ],
        false,
    ),
)]
// endregion
// region NE, S, no exposed edges present, one neighbor association, no wanted slot
#[case::ne_s_no_exposed_edges_present_one_neighbor_association_no_wanted_slot(
    pad_coordinates_randomly((4, 4)),
    None,
    // ╭─────────────╮
    // │ 0 0 0 0 ₅   │
    // │ 0       0   │
    // │ 0   0   0   │
    // │     0       │
    // │   ₅ 0   0   │
    // │     0 0 0   │
    // │ 0           │
    // │ 0           │
    // ╰─────────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(rand_usize(5, 10)),
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            None,
        ],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(rand_usize(5, 10)),
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            None,
            None,
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            None,
            None,
            None,
        ],
    ]),
    (vec![HashSet::from([Direction::South])], false),
)]
// endregion
// region NE, no exposed edges present, one neighbor association, no wanted slot
#[case::ne_no_exposed_edges_present_one_neighbor_association_no_wanted_slot(
    pad_coordinates_randomly((3, 2)),
    None,
    // ╭─────────╮
    // │     0 0 │
    // │ 0     0 │
    // │ 0     0 │
    // │ 0 0 0 0 │
    // │     0   │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
    ]),
    (vec![HashSet::from([Direction::North, Direction::East])], false),
)]
// endregion
// region NE, no exposed edges present, one neighbor association, no wanted slot, corner
#[case::ne_no_exposed_edges_present_one_neighbor_association_no_wanted_slot_corner(
    (5 + *RANDOM_USIZE * 3, 1),
    None,
    // ╭─────────╮
    // │ 0 0 0 0 │
    // │ 0 ? ? 0 │
    // │ 0 0 ? 0 │
    // │     0 0 │
    // │     0 0 │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_or_none(),
            create_grid_slot_or_none(),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_or_none(),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
    ]),
    (vec![HashSet::from([Direction::North, Direction::East])], false),
)]
// endregion
// region NW, no exposed edges present, one neighbor association, no wanted slot
#[case::nw_no_exposed_edges_present_one_neighbor_association_no_wanted_slot(
    pad_coordinates_randomly((3, 2)),
    None,
    // ╭─────────╮
    // │     0 0 │
    // │       0 │
    // │     0 0 │
    // │ 0 0 0 0 │
    // │     0   │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [None, None, None, None, create_grid_slot_with_some_tile_id(0)],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
    ]),
    (vec![HashSet::from([Direction::North, Direction::West])], false),
)]
// endregion
// region ES, no exposed edges present, one neighbor association, no wanted slot
#[case::es_no_exposed_edges_present_one_neighbor_association_no_wanted_slot(
    pad_coordinates_randomly((3, 2)),
    None,
    // ╭─────────╮
    // │     0 0 │
    // │ 0 0   0 │
    // │ 0     0 │
    // │ 0     0 │
    // │     0   │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
    ]),
    (vec![HashSet::from([Direction::East, Direction::South])], false),
)]
// endregion
// region ES, no exposed edges present, one neighbor association, altern., no wanted slot
#[case::es_no_exposed_edges_present_one_neighbor_association_altern_no_wanted_slot(
    pad_coordinates_randomly((3, 2)),
    None,
    // ╭─────────╮
    // │     0 0 │
    // │ 0 0   0 │
    // │ 0     0 │
    // │       0 │
    // │     0   │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [None, None, None, None, create_grid_slot_with_some_tile_id(0)],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
    ]),
    (vec![HashSet::from([Direction::East, Direction::South])], false),
)]
// endregion
// region SW, no exposed edges present, one neighbor association, no wanted slot
#[case::sw_no_exposed_edges_present_one_neighbor_association_no_wanted_slot(
    pad_coordinates_randomly((3, 2)),
    None,
    // ╭─────────╮
    // │     0 0 │
    // │ 0 0   0 │
    // │     0 0 │
    // │       0 │
    // │     0   │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [None, None, None, None, create_grid_slot_with_some_tile_id(0)],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
    ]),
    (vec![HashSet::from([Direction::South, Direction::West])], false),
)]
// endregion
// region SW, no exposed edges present, one neighbor association, altern., no wanted slot
#[case::sw_no_exposed_edges_present_one_neighbor_association_altern_no_wanted_slot(
    pad_coordinates_randomly((3, 2)),
    None,
    // ╭─────────╮
    // │     0 0 │
    // │   0   0 │
    // │     0 0 │
    // │       0 │
    // │     0   │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [None, None, None, None, create_grid_slot_with_some_tile_id(0)],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
    ]),
    (vec![HashSet::from([Direction::South, Direction::West])], false),
)]
// endregion
// region SW, no exposed edges present, one neighbor association, no wanted slot, corner
#[case::sw_no_exposed_edges_present_one_neighbor_association_no_wanted_slot_corner(
    (1, 4 + *RANDOM_USIZE * 4),
    None,
    // ╭─────────╮
    // │ 0 0     │
    // │ 0 0     │
    // │ 0 ? 0 0 │
    // │ 0 ? ? 0 │
    // │ 0 0 0 0 │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_or_none(),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_or_none(),
            create_grid_slot_or_none(),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
    ]),
    (vec![HashSet::from([Direction::South, Direction::West])], false),
)]
// endregion
// region NE, exposed edges present, no neighbor associations, no wanted slot
#[case::ne_exposed_edges_present_no_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((3, 2)),
    None,
    // ╭───────────╮
    // │       0 0 │
    // │   0     0 │
    // │   0     0 │
    // │   0 0 0 0 │
    // │       ₄   │
    // ╰───────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(rand_usize(4, 9)),
            None,
        ],
    ]),
    (vec![], false),
)]
// endregion
// region NE, exposed edges present, no neighbor associations, wanted slot SW reached
#[case::ne_exposed_edges_present_no_neighbor_associations_no_wanted_slot_sw_reached(
    pad_coordinates_randomly((3, 2)),
    Some(pad_coordinates_randomly((5, 3))),
    // ╭───────────╮
    // │       0 0 │
    // │   0     0 │
    // │   0     0 │
    // │   0 0 0 0 │
    // │     W ₄   │
    // ╰───────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(rand_usize(4, 9)),
            None,
        ],
    ]),
    (vec![], true),
)]
// endregion
// region N, E, no exposed edges present, two neighbor associations, no wanted slot
#[case::n_e_no_exposed_edges_present_two_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((3, 2)),
    None,
    // ╭─────────╮
    // │     0 0 │
    // │ 0   0 0 │
    // │ 0     0 │
    // │ 0 0 0 0 │
    // │     0   │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
    ]),
    (vec![HashSet::from([Direction::East]), HashSet::from([Direction::North])], false),
)]
// endregion
// region N, E, exposed edges present, one neighbor association, no wanted slot
#[case::n_e_exposed_edges_present_one_neighbor_association_no_wanted_slot(
    pad_coordinates_randomly((3, 2)),
    None,
    // ╭─────────╮
    // │     ₄ 0 │
    // │ 0   0 0 │
    // │ 0     0 │
    // │ 0 0 0 0 │
    // │     0   │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(rand_usize(4, 9)),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
    ]),
    (vec![HashSet::from([Direction::East])], false),
)]
// endregion
// region S, W, exposed edges present, two neighbor associations, no wanted slot
#[case::s_w_exposed_edges_present_two_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((3, 3)),
    None,
    // ╭───────────╮
    // │       4 0 │
    // │   0 0 0 0 │
    // │ 0     0 0 │
    // │   0   0 0 │
    // │   0 0 0   │
    // ╰───────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None, None],
        [
            None,
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(4),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
    ]),
    (vec![HashSet::from([Direction::West]), HashSet::from([Direction::South])], false),
)]
// endregion
// region N, S, exposed edges present, one neighbor association, no wanted slot
#[case::n_s_exposed_edges_present_one_neighbor_association_no_wanted_slot(
    pad_coordinates_randomly((3, 2)),
    None,
    // ╭─────────╮
    // │     ₄ 0 │
    // │ 0   0 0 │
    // │ 0   0 0 │
    // │ 0   0 0 │
    // │ 0 0 0   │
    // ╰─────────╯
    pad_grid_randomly(array![
        [None, None, None, None, None],
        [
            None,
            None,
            None,
            create_grid_slot_with_some_tile_id(rand_usize(4, 9)),
            create_grid_slot_or_none(),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            None,
        ],
    ]),
    (vec![HashSet::from([Direction::South])], false),
)]
// endregion
// region N, no exposed edges present, one neighbor association, no wanted slot
#[case::n_no_exposed_edges_present_one_neighbor_association_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │       │
    // │ 0   0 │
    // │ 0 0 0 │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, None, None, None],
        [None, create_grid_slot_with_some_tile_id(0), None,
create_grid_slot_with_some_tile_id(0)],         [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
    ]),
    (vec![HashSet::from([Direction::North])], false),
)]
// endregion
// region E, no exposed edges present, one neighbor association, no wanted slot
#[case::e_no_exposed_edges_present_one_neighbor_association_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │ 0 0   │
    // │ 0     │
    // │ 0 0 0 │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, create_grid_slot_with_some_tile_id(0), create_grid_slot_with_some_tile_id(0), None],
        [None, create_grid_slot_with_some_tile_id(0), None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
    ]),
    (vec![HashSet::from([Direction::East])], false),
)]
// endregion
// region E, no exposed edges present, one neighbor association, altern., no wanted slot
#[case::e_no_exposed_edges_present_one_neighbor_association_altern_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │ 0 0   │
    // │ 0     │
    // │ 0 0   │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, create_grid_slot_with_some_tile_id(0), create_grid_slot_with_some_tile_id(0), None],
        [None, create_grid_slot_with_some_tile_id(0), None, None],
        [None, create_grid_slot_with_some_tile_id(0), create_grid_slot_with_some_tile_id(0), None],
    ]),
    (vec![HashSet::from([Direction::East])], false),
)]
// endregion
// region S, no exposed edges present, one neighbor association, no wanted slot
#[case::s_no_exposed_edges_present_one_neighbor_association_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │ 0 0 0 │
    // │ 0   0 │
    // │ 0   0 │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [None, create_grid_slot_with_some_tile_id(0), None, create_grid_slot_with_some_tile_id(0)],
        [None, create_grid_slot_with_some_tile_id(0), None, create_grid_slot_with_some_tile_id(0)],
    ]),
    (vec![HashSet::from([Direction::South])], false),
)]
// endregion
// region S, no exposed edges present, one neighbor association, altern, no wanted slot
#[case::s_no_exposed_edges_present_one_neighbor_association_altern_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │ 0 0 0 │
    // │ 0   0 │
    // │       │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [None, create_grid_slot_with_some_tile_id(0), None, create_grid_slot_with_some_tile_id(0)],
        [None, None, None, None],
    ]),
    (vec![HashSet::from([Direction::South])], false),
)]
// endregion
// region W, no exposed edges present, one neighbor association, no wanted slot
#[case::w_no_exposed_edges_present_one_neighbor_association_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │ 0 0 0 │
    // │     0 │
    // │ 0 0 0 │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0)
        ],
        [None, None, None, create_grid_slot_with_some_tile_id(0)],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
    ]),
    (vec![HashSet::from([Direction::West])], false),
)]
// endregion
// region N, exposed edges present, no neighbor associations, no wanted slot
#[case::n_exposed_edges_present_no_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │       │
    // │ 1   0 │
    // │ 0 0 0 │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, None, None, None],
        [None, create_grid_slot_with_some_tile_id(1), None, create_grid_slot_with_some_tile_id(0)],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
    ]),
    (vec![], false),
)]
// endregion
// region E, exposed edges present, no neighbor associations, no wanted slot
#[case::e_exposed_edges_present_no_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │ 0 2   │
    // │ 0     │
    // │ 0 0 0 │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [None, create_grid_slot_with_some_tile_id(0), create_grid_slot_with_some_tile_id(2), None],
        [None, create_grid_slot_with_some_tile_id(0), None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
    ]),
    (vec![], false),
)]
// endregion
// region S, exposed edges present, no neighbor associations, no wanted slot
#[case::s_exposed_edges_present_no_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │ 0 0 0 │
    // │ 0   0 │
    // │ 2   0 │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
        [None, create_grid_slot_with_some_tile_id(0), None, create_grid_slot_with_some_tile_id(0)],
        [None, create_grid_slot_with_some_tile_id(2), None, create_grid_slot_with_some_tile_id(0)],
    ]),
    (vec![], false),
)]
// endregion
// region W, exposed edges present, no neighbor associations, no wanted slot
#[case::w_exposed_edges_present_no_neighbor_associations_no_wanted_slot(
    pad_coordinates_randomly((2, 2)),
    None,
    // ╭───────╮
    // │ 3 0 0 │
    // │     0 │
    // │ 0 0 0 │
    // ╰───────╯
    pad_grid_randomly(array![
        [None, None, None, None],
        [
            None,
            create_grid_slot_with_some_tile_id(3),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0)
        ],
        [None, None, None, create_grid_slot_with_some_tile_id(0)],
        [
            None,
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
            create_grid_slot_with_some_tile_id(0),
        ],
    ]),
    (vec![], false),
)]
// endregion

fn test_traverse_neighbor_associations(
    #[case] current_slot: (usize, usize),
    #[case] wanted_slot: Option<(usize, usize)>,
    #[case] grid: Array2<Option<GridSlot>>,
    #[case] expected_result: (Vec<HashSet<Direction>>, bool),
) {
    let tile_list = neighbor_association_tile_list();
    let slot_grid = SlotGrid {
        num_rows: grid.nrows(),
        num_cols: grid.ncols(),
        grid,
        border_tile_id: if rand_bool() {
            None
        } else {
            Some(rand_usize(0, 9))
        },
        tile_connections: TileConnectionArray::new(&tile_list.tiles),
        tile_list,
        missing_tile_policy: random_missing_tile_policy(),
        tile_selection_policy: random_tile_selection_policy(),
        vacancy_policy: RANDOM_VACANCY_POLICY.clone(),
        current_slot,
        current_predecessor: random_predecessor(),
        last_leaves: random_last_leaves(),
        exposed_edge_count: rand_usize(0, 19),
    };

    let result = slot_grid.traverse_neighbor_associations(wanted_slot);

    assert_eq!(result, expected_result);
    // Access slot_grid to ensure it was not moved.
    drop(slot_grid);
}

use crate::tiling::{Direction, GridSlot, SlotGrid};
